---
title: Containerize a Langflow application
slug: /develop-application
---

import Icon from "@site/src/components/icon";
import PartialPodmanAlt from '@site/docs/_partial-podman-alt.mdx';

<PartialPodmanAlt />

Designing flows in the visual editor is only the first step in building an application that uses Langflow.

Once you have a functional flow, you can use that flow in a larger application, such as a website or mobile app.
Because Langflow is both an IDE and a runtime, you can use Langflow to build and test your flows locally, and then package and serve your flows in a production environment.

This guide introduces application development with Langflow from initial setup through packaging and deployment.
This documentation doesn't explain how to write a complete application; it only describes how to include Langflow in the context of a larger application.

## Directory structure

The following example describes the directory structure for a minimal Langflow application:

```text
LANGFLOW-APPLICATION/
├── docker.env
├── Dockerfile
├── flows/
│   ├── flow1.json
│   └── flow2.json
├── langflow-config-dir/
├── README.md
```

This directory contains the following:

* [`docker.env`](#docker-env): This file is copied to the Docker image as a `.env` file in the container root.
* [`Dockerfile`](#dockerfile): This file controls how your Langflow image is built.
* [`/flows`](#flows): This folder holds the flows you want to host, which are the flows that your application uses.
* `/langflow-config-dir`: This folder is referenced in the Dockerfile as the location for your Langflow deployment's configuration files, database, and logs.
* `README.md`: This is a typical README file for your application's documentation.

This is a minimal example of a Langflow application directory.
Your application might have additional files and folders, such as a `/components` folder for custom components, or a `pyproject.toml` file for additional dependencies.

### Package management

The base Langflow Docker image includes the Langflow core dependencies because it uses `langflowai/langflow:latest` as the parent image.

If your application requires additional dependencies, create a [`pyproject.toml`](https://packaging.python.org/en/latest/guides/writing-pyproject-toml) file for the additional dependencies.
For more information, see [Install custom dependencies](/install-custom-dependencies).

To deploy an application with additional dependencies to Docker, you must copy the `pyproject.toml` and `uv.lock` files to the Docker image.
To do this, add the following to your Langflow application's Dockerfile:

```text
COPY pyproject.toml uv.lock /app/
```

### Environment variables {#docker-env}

The `docker.env` file is a `.env` file loaded into your Docker image.
It contains [Langflow environment variables](/environment-variables) that are used in flows or control Langflow's behavior, such as authentication, database storage, API keys, and server configurations.
For example:

```text
LANGFLOW_AUTO_LOGIN=True
LANGFLOW_SAVE_DB_IN_CONFIG_DIR=True
LANGFLOW_BASE_URL=http://0.0.0.0:7860
OPENAI_API_KEY=sk-...
```

You can set environment variables in the Dockerfile as well.
However, if you set an environment variable in both `docker.env` and the Dockerfile, Langflow uses the value set in `docker.env`.

Langflow can also [create global variables from your environment variables](/configuration-global-variables#add-custom-global-variables-from-the-environment), or [use environment variables as a backup for missing global variables](/configuration-global-variables#use-environment-variables-for-missing-global-variables).

### Secrets

For simplicity, the examples in the Langflow documentation might use direct references to API keys and other sensitive values.
In your own applications, you should always follow industry best practices for managing secrets, such as using environment variables or secret management tools.

For information about generating authentication keys and managing secrets in Langflow, see [API keys and authentication](/api-keys-and-authentication).

### Storage

By default, Langflow uses an [SQLite](https://www.sqlite.org/) database for storage.
If you prefer to use PostgreSQL, see [Configure an external PostgreSQL database](/configuration-custom-database).

For more information about storage, including cache and memory, see [Memory management options](/memory).

### Flows {#flows}

Your local Langflow instance might have many flows for different applications.
When you package Langflow as a dependency of an application, you only want to include the flows your application uses.

1. [Export flows](/concepts-flows-import) that are relevant to your application.

    If you have chained flows (flows that trigger other flows), make sure you export _all_ necessary flows.

2. Add the exported Langflow JSON files to the `/flows` folder in your application directory.

### Components

The <Icon name="Component" aria-hidden="true" /> **Core components** and <Icon name="Blocks" aria-hidden="true" /> [**Bundles**] that you see in the Langflow visual editor are automatically included in the base Langflow Docker image.

If you have any [custom components](/components-custom-components) that you created for your application, you must include these components in your application directory:

1. Create a `/components` folder in your application directory.
2. Add your custom component files to the `/components` folder.
3. Specify the path to `/components` in your `docker.env`.

## Langflow Dockerfile {#dockerfile}

The Dockerfile determines how your Langflow image is built, including the dependencies, flows, components, and configuration files.

At minimum, you need to specify the base Langflow image, create the necessary folders in the container, copy folders and files to the container, and provide a startup command.

```dockerfile
# Use the latest version of the base Langflow image
FROM langflowai/langflow:latest

# Create folders and set the working directory in the container
RUN mkdir /app/flows
RUN mkdir /app/langflow-config-dir
WORKDIR /app

# Copy flows, langflow-config-dir, and docker.env to the container
COPY flows /app/flows
COPY langflow-config-dir /app/langflow-config-dir
COPY docker.env /app/.env

# Optional: Copy custom components to the container
COPY components /app/components

# Optional: Use custom dependencies
COPY pyproject.toml uv.lock /app/

# Set environment variables if not set in docker.env
ENV PYTHONPATH=/app
ENV LANGFLOW_LOAD_FLOWS_PATH=/app/flows
ENV LANGFLOW_CONFIG_DIR=/app/langflow-config-dir
ENV LANGFLOW_COMPONENTS_PATH=/app/components
ENV LANGFLOW_LOG_ENV=container

# Command to run the Langflow server on port 7860
EXPOSE 7860
CMD ["langflow", "run", "--backend-only", "--env-file","/app/.env","--host", "0.0.0.0", "--port", "7860"]
```

The environment variables set directly in this Dockerfile specify resource paths for Langflow.
If these variables are also set in `docker.env`, the values in `docker.env` override the values set in the Dockerfile.

In this example, `ENV LANGFLOW_LOG_ENV=container` sets the logging behavior for serialized JSON to `stdout` to track the application's behavior in a containerized environment. For more information, see [Logging](/logging).

### Backend-only mode

The `--backend-only` flag in `CMD` starts Langflow in backend-only mode, which provides programmatic access only.
This is recommended when running Langflow as a dependency of an application where you don't need access to the visual editor.

If you want to serve the Langflow visual editor _and_ backend, then omit `--backend-only`.

For more information, see [Deploy Langflow on Docker](/deployment-docker).

## Test your Langflow Docker image

Build and run your Langflow Docker image to test it.

This example runs the container locally.
For information about publishing your image on Docker Hub and running a Langflow container remotely, see [Deploy to Docker Hub and Kubernetes](#deploy-docker).

1. Build the Docker image:

    ```bash
    docker build -t langflow-pokedex:1.2.0 .
    ```

2. Run the Docker container to start your Langflow server:

    ```bash
    docker run -p 7860:7860 langflow-pokedex:1.2.0
    ```

3. To confirm that the container is serving your flows as expected, use the Langflow API to run a flow:

    1. Open one of the JSON files in your application's `/flows` folder, and then find the flow's `id` in the  [additional metadata and project information](/concepts-flows-import#additional-metadata-and-project-information).

        There are many `id` values; make sure you get the ID for the entire flow, not the ID for an individual component.
        If your flow is complex, try searching for the flow's name, which is typically near the flow's `id`.

        ```json
        "name": "Basic Prompting",
        "description": "Perform basic prompting with an OpenAI model.",
        "id": "e4167236-938f-4aca-845b-21de3f399858",
        ```

    2. Send a POST request to the [`/v1/run/$FLOW_ID`](/api-flows-run#run-flow) endpoint using the flow ID from the previous step .

        The following example runs a simple LLM chat flow that responds to a chat input string.
        If necessary, modify the payload for your flow.
        For example, if your flow doesn't have a **Chat Input** component, you must modify the payload to provide the expected input for your flow.

        ```bash
        curl --request POST \
          --url 'http://localhost:7860/api/v1/run/e4167236-938f-4aca-845b-21de3f399858?stream=true' \
          --header 'Content-Type: application/json' \
          --data '{
            "input_value": "Tell me about Charizard.",
            "output_type": "chat",
            "input_type": "chat",
            "session_id": "charizard_test_request"
        }'
        ```

        <details>
        <summary>About this example</summary>

        This command runs the **Pokédex** template flow.
        It provides chat input about a specific Pokémon, uses an optional custom `session_id`, and enables response streaming with `?stream=true`.

        The default [session ID](/session-id) is the flow ID.
        Custom session IDs can help isolate unique conversation threads to keep the LLM's context clean, and they can help identify specific conversations in flow logs to make debugging easier.

        This command uses response streaming because the Pokédex flow can return a large amount of text.
        To use batching, set `?stream=false`.

        </details>

      3. Verify that the request succeeds and the response is valid, depending on the specific flow you ran.

          This confirms that your Langflow Docker image is correctly configured and this flow is accessible through the Langflow API server that is hosted on the container.
          When you build and test your entire application stack, your front-end application can use Langflow API requests to trigger the flows served by your Langflow container in the same way you manually tested the flow in the previous step.

          This example triggered a flow by sending chat input to the `/v1/run/$FLOW_ID` endpoint.
          For more examples of flow triggers, see [Trigger flows with webhooks](/webhook) and the tutorial to [Create a chatbot that can ingest files](/chat-with-files).

## Deploy to Docker Hub and Kubernetes {#deploy-docker}

When you're ready to share your application with the world, you need to serve Langflow in a production environment.
For more information about deploying Langflow, see the following:

* [Learn about Langflow deployments](/deployment-overview)
* [Deploy Langflow on Docker](/deployment-docker)
* [Deploy the Langflow production environment on Kubernetes](/deployment-kubernetes-prod)